home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / src / linux-headers-2.6.28-15 / include / asm-m32r / bitops.h < prev    next >
Encoding:
C/C++ Source or Header  |  2008-12-24  |  6.2 KB  |  275 lines

  1. #ifndef _ASM_M32R_BITOPS_H
  2. #define _ASM_M32R_BITOPS_H
  3.  
  4. /*
  5.  *  linux/include/asm-m32r/bitops.h
  6.  *
  7.  *  Copyright 1992, Linus Torvalds.
  8.  *
  9.  *  M32R version:
  10.  *    Copyright (C) 2001, 2002  Hitoshi Yamamoto
  11.  *    Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
  12.  */
  13.  
  14. #ifndef _LINUX_BITOPS_H
  15. #error only <linux/bitops.h> can be included directly
  16. #endif
  17.  
  18. #include <linux/compiler.h>
  19. #include <asm/assembler.h>
  20. #include <asm/system.h>
  21. #include <asm/byteorder.h>
  22. #include <asm/types.h>
  23.  
  24. /*
  25.  * These have to be done with inline assembly: that way the bit-setting
  26.  * is guaranteed to be atomic. All bit operations return 0 if the bit
  27.  * was cleared before the operation and != 0 if it was not.
  28.  *
  29.  * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
  30.  */
  31.  
  32. /**
  33.  * set_bit - Atomically set a bit in memory
  34.  * @nr: the bit to set
  35.  * @addr: the address to start counting from
  36.  *
  37.  * This function is atomic and may not be reordered.  See __set_bit()
  38.  * if you do not require the atomic guarantees.
  39.  * Note that @nr may be almost arbitrarily large; this function is not
  40.  * restricted to acting on a single-word quantity.
  41.  */
  42. static __inline__ void set_bit(int nr, volatile void * addr)
  43. {
  44.     __u32 mask;
  45.     volatile __u32 *a = addr;
  46.     unsigned long flags;
  47.     unsigned long tmp;
  48.  
  49.     a += (nr >> 5);
  50.     mask = (1 << (nr & 0x1F));
  51.  
  52.     local_irq_save(flags);
  53.     __asm__ __volatile__ (
  54.         DCACHE_CLEAR("%0", "r6", "%1")
  55.         M32R_LOCK" %0, @%1;        \n\t"
  56.         "or    %0, %2;            \n\t"
  57.         M32R_UNLOCK" %0, @%1;        \n\t"
  58.         : "=&r" (tmp)
  59.         : "r" (a), "r" (mask)
  60.         : "memory"
  61. #ifdef CONFIG_CHIP_M32700_TS1
  62.         , "r6"
  63. #endif    /* CONFIG_CHIP_M32700_TS1 */
  64.     );
  65.     local_irq_restore(flags);
  66. }
  67.  
  68. /**
  69.  * clear_bit - Clears a bit in memory
  70.  * @nr: Bit to clear
  71.  * @addr: Address to start counting from
  72.  *
  73.  * clear_bit() is atomic and may not be reordered.  However, it does
  74.  * not contain a memory barrier, so if it is used for locking purposes,
  75.  * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
  76.  * in order to ensure changes are visible on other processors.
  77.  */
  78. static __inline__ void clear_bit(int nr, volatile void * addr)
  79. {
  80.     __u32 mask;
  81.     volatile __u32 *a = addr;
  82.     unsigned long flags;
  83.     unsigned long tmp;
  84.  
  85.     a += (nr >> 5);
  86.     mask = (1 << (nr & 0x1F));
  87.  
  88.     local_irq_save(flags);
  89.  
  90.     __asm__ __volatile__ (
  91.         DCACHE_CLEAR("%0", "r6", "%1")
  92.         M32R_LOCK" %0, @%1;        \n\t"
  93.         "and    %0, %2;            \n\t"
  94.         M32R_UNLOCK" %0, @%1;        \n\t"
  95.         : "=&r" (tmp)
  96.         : "r" (a), "r" (~mask)
  97.         : "memory"
  98. #ifdef CONFIG_CHIP_M32700_TS1
  99.         , "r6"
  100. #endif    /* CONFIG_CHIP_M32700_TS1 */
  101.     );
  102.     local_irq_restore(flags);
  103. }
  104.  
  105. #define smp_mb__before_clear_bit()    barrier()
  106. #define smp_mb__after_clear_bit()    barrier()
  107.  
  108. /**
  109.  * change_bit - Toggle a bit in memory
  110.  * @nr: Bit to clear
  111.  * @addr: Address to start counting from
  112.  *
  113.  * change_bit() is atomic and may not be reordered.
  114.  * Note that @nr may be almost arbitrarily large; this function is not
  115.  * restricted to acting on a single-word quantity.
  116.  */
  117. static __inline__ void change_bit(int nr, volatile void * addr)
  118. {
  119.     __u32  mask;
  120.     volatile __u32  *a = addr;
  121.     unsigned long flags;
  122.     unsigned long tmp;
  123.  
  124.     a += (nr >> 5);
  125.     mask = (1 << (nr & 0x1F));
  126.  
  127.     local_irq_save(flags);
  128.     __asm__ __volatile__ (
  129.         DCACHE_CLEAR("%0", "r6", "%1")
  130.         M32R_LOCK" %0, @%1;        \n\t"
  131.         "xor    %0, %2;            \n\t"
  132.         M32R_UNLOCK" %0, @%1;        \n\t"
  133.         : "=&r" (tmp)
  134.         : "r" (a), "r" (mask)
  135.         : "memory"
  136. #ifdef CONFIG_CHIP_M32700_TS1
  137.         , "r6"
  138. #endif    /* CONFIG_CHIP_M32700_TS1 */
  139.     );
  140.     local_irq_restore(flags);
  141. }
  142.  
  143. /**
  144.  * test_and_set_bit - Set a bit and return its old value
  145.  * @nr: Bit to set
  146.  * @addr: Address to count from
  147.  *
  148.  * This operation is atomic and cannot be reordered.
  149.  * It also implies a memory barrier.
  150.  */
  151. static __inline__ int test_and_set_bit(int nr, volatile void * addr)
  152. {
  153.     __u32 mask, oldbit;
  154.     volatile __u32 *a = addr;
  155.     unsigned long flags;
  156.     unsigned long tmp;
  157.  
  158.     a += (nr >> 5);
  159.     mask = (1 << (nr & 0x1F));
  160.  
  161.     local_irq_save(flags);
  162.     __asm__ __volatile__ (
  163.         DCACHE_CLEAR("%0", "%1", "%2")
  164.         M32R_LOCK" %0, @%2;        \n\t"
  165.         "mv    %1, %0;            \n\t"
  166.         "and    %0, %3;            \n\t"
  167.         "or    %1, %3;            \n\t"
  168.         M32R_UNLOCK" %1, @%2;        \n\t"
  169.         : "=&r" (oldbit), "=&r" (tmp)
  170.         : "r" (a), "r" (mask)
  171.         : "memory"
  172.     );
  173.     local_irq_restore(flags);
  174.  
  175.     return (oldbit != 0);
  176. }
  177.  
  178. /**
  179.  * test_and_clear_bit - Clear a bit and return its old value
  180.  * @nr: Bit to set
  181.  * @addr: Address to count from
  182.  *
  183.  * This operation is atomic and cannot be reordered.
  184.  * It also implies a memory barrier.
  185.  */
  186. static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
  187. {
  188.     __u32 mask, oldbit;
  189.     volatile __u32 *a = addr;
  190.     unsigned long flags;
  191.     unsigned long tmp;
  192.  
  193.     a += (nr >> 5);
  194.     mask = (1 << (nr & 0x1F));
  195.  
  196.     local_irq_save(flags);
  197.  
  198.     __asm__ __volatile__ (
  199.         DCACHE_CLEAR("%0", "%1", "%3")
  200.         M32R_LOCK" %0, @%3;        \n\t"
  201.         "mv    %1, %0;            \n\t"
  202.         "and    %0, %2;            \n\t"
  203.         "not    %2, %2;            \n\t"
  204.         "and    %1, %2;            \n\t"
  205.         M32R_UNLOCK" %1, @%3;        \n\t"
  206.         : "=&r" (oldbit), "=&r" (tmp), "+r" (mask)
  207.         : "r" (a)
  208.         : "memory"
  209.     );
  210.     local_irq_restore(flags);
  211.  
  212.     return (oldbit != 0);
  213. }
  214.  
  215. /**
  216.  * test_and_change_bit - Change a bit and return its old value
  217.  * @nr: Bit to set
  218.  * @addr: Address to count from
  219.  *
  220.  * This operation is atomic and cannot be reordered.
  221.  * It also implies a memory barrier.
  222.  */
  223. static __inline__ int test_and_change_bit(int nr, volatile void * addr)
  224. {
  225.     __u32 mask, oldbit;
  226.     volatile __u32 *a = addr;
  227.     unsigned long flags;
  228.     unsigned long tmp;
  229.  
  230.     a += (nr >> 5);
  231.     mask = (1 << (nr & 0x1F));
  232.  
  233.     local_irq_save(flags);
  234.     __asm__ __volatile__ (
  235.         DCACHE_CLEAR("%0", "%1", "%2")
  236.         M32R_LOCK" %0, @%2;        \n\t"
  237.         "mv    %1, %0;            \n\t"
  238.         "and    %0, %3;            \n\t"
  239.         "xor    %1, %3;            \n\t"
  240.         M32R_UNLOCK" %1, @%2;        \n\t"
  241.         : "=&r" (oldbit), "=&r" (tmp)
  242.         : "r" (a), "r" (mask)
  243.         : "memory"
  244.     );
  245.     local_irq_restore(flags);
  246.  
  247.     return (oldbit != 0);
  248. }
  249.  
  250. #include <asm-generic/bitops/non-atomic.h>
  251. #include <asm-generic/bitops/ffz.h>
  252. #include <asm-generic/bitops/__ffs.h>
  253. #include <asm-generic/bitops/fls.h>
  254. #include <asm-generic/bitops/fls64.h>
  255.  
  256. #ifdef __KERNEL__
  257.  
  258. #include <asm-generic/bitops/sched.h>
  259. #include <asm-generic/bitops/find.h>
  260. #include <asm-generic/bitops/ffs.h>
  261. #include <asm-generic/bitops/hweight.h>
  262. #include <asm-generic/bitops/lock.h>
  263.  
  264. #endif /* __KERNEL__ */
  265.  
  266. #ifdef __KERNEL__
  267.  
  268. #include <asm-generic/bitops/ext2-non-atomic.h>
  269. #include <asm-generic/bitops/ext2-atomic.h>
  270. #include <asm-generic/bitops/minix.h>
  271.  
  272. #endif /* __KERNEL__ */
  273.  
  274. #endif /* _ASM_M32R_BITOPS_H */
  275.